package com.dss.wap.core.webserver;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.util.ArrayList;

import org.eclipse.draw2d.geometry.Rectangle;

import com.dss.dsc.GlobalDefine;
import com.dss.dsc.commands.CollapseCommand;
import com.dss.dsc.error_detecting.RefTargetStrategy;
import com.dss.dsc.model.AbstractConnectionModel;
import com.dss.dsc.model.AbstractModel;
import com.dss.dsc.model.ContentsModel;
import com.dss.dsc.model.DSDiagramFactory;
import com.dss.dsc.model.DynamicCreation;
import com.dss.dsc.model.Interaction;
import com.dss.dsc.model.Node;
import com.dss.dsc.model.RelationLink;
import com.dss.dsc.model.SimpleData;
import com.dss.dsc.model.SimpleEA;
import com.dss.dsc.model.Specialization;
import com.dss.dsc.model.Transition;

import dsc.model.Array;
import dsc.model.util.GefModelUtil;
import dsc.model.util.JsonConvert;
import dsc.model.view.AbstractSysForViewModel;
import dsc.model.view.SysForView;
import dsc.model.view.SysForView.Complete.Link;
import dsc.model.view.SysForView.Complete.Link.LinkShowInfo;
import dsc.model.view.SysForView.Complete.Link.LinkType;
import dsc.model.view.SysForView.Complete.Sys.Content;
import dsc.model.view.SysForView.Complete;
import dsc.model.view.SysForView.Complete.Sys;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.BeginPoint;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.BeginPoint.Point;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.EndPoint;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.ExitPoint;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.PreCondition;
import dsc.model.view.SysForView.Complete.Sys.Content.Composite.SubArray;
import dsc.model.view.SysForView.Complete.Sys.Property;
import dsc.model.view.SysForView.Complete.Sys.ShowInfo;
//import dsc.model.view.SysForView.Complete.Sys.ShowInfo.Rectangle;
import dsc.model.view.SysForView.Complete.Sys.SpecSys;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SNameLabel;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SNameLabel.NameLabelType;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SProto;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SWork;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SWork.DeriveInfo;
import dsc.model.view.SysForView.Complete.Sys.SpecSys.SWork.DeriveInfo.DeriveFlag;
import dsc.model.view.SysForView.Complete.Sys.Type;
import dsc.model.view.YesNo;

/**
 * 
 * @author wl 此类是用于将SysForView 转换成GEF的模型
 */
public class GefConvert {

	private static GefConvert instance;
	private ArrayList<AbstractModel> models = new ArrayList<AbstractModel>();

	public static GefConvert getInstance() {
		if (instance == null) {
			instance = new GefConvert();
		}
		return instance;
	}

	public ContentsModel convertSysForView(SysForView sysForView) {
		ContentsModel contentModel = new ContentsModel();
		models.clear();
		if (sysForView.pick == SysForView.complete_id) {
			/*Array<Sys>*/Sys systems = ((Complete) sysForView.picked).sys;
			Array<Link> links = ((Complete) sysForView.picked).link;
			if(systems != null){
				for (Sys sys : ((Composite)systems.content.picked).subSys.inst) {
					AbstractModel model = convertSys(sys);
					if(model != null){
						contentModel.addChild(model);
					}					
				}
			}
			if(links != null){
				System.out.println(links.inst.size());
				for (Link link : links.inst){
					AbstractConnectionModel conn = convertLink(link);
					if(conn == null){
						continue;
					}
					
				}		
			}				
		}
		return contentModel;
	}

	public AbstractModel convertSys(Sys sys) {
		AbstractModel model = null;
		if (sys.content.pick == Content.simple_id) {
			model = convertSimple(sys);
		} else if (sys.content.pick == Content.composite_id) {
			model = convertComposite(sys);
		}
		if(model == null){
			return model;
		}
		model.setName(sys.name.toString());		
		model.setConstraint(convertConstraint(sys));
		if(model instanceof Node){
			if(sys.showInfo.showLabel.name().equals(YesNo.no.name())){
				((Node) model).setShowName(false);
			}else{
				((Node) model).setShowName(true);
			}
			if(sys.showInfo.showContent.name().equals(YesNo.no.name())){
				((Node) model).setCollapsed(true);
			}else{
				((Node) model).setCollapsed(false);
			}
		}		
		models.add(model);
		return model;
	}

	private AbstractModel convertSimple(Sys sys) {
		AbstractModel model = null;
		if (sys.type.name().equals(Type.Data.name())) {
			model = DSDiagramFactory.createSimpleData();
			((SimpleData) model).setType2(sys.content.picked.toString());
		} else if (sys.type.equals(Type.Predicate)) {
			model = DSDiagramFactory.createBinarySimplePredicate();
		} else if (sys.type.name().equals(Type.Protocol.name())) {
			model = DSDiagramFactory.createSimpleProtocol();
			if(sys.specSys.pick == SpecSys.specProtocol_id){
				SProto sp = (SProto) sys.specSys.picked;
				((SimpleEA)model).setSender(sp.from.toString());
				((SimpleEA)model).setReceiver(sp.to.toString());
			}
		} else if (sys.type.name().equals(Type.System.name())) {
			model = DSDiagramFactory.createSimpleSystem();
		} else if (sys.type.name().equals(Type.Work.name())) {
			model = DSDiagramFactory.createSimpleWork();
		} else if (sys.type.name().equals(Type.NameLabel)){
			model = DSDiagramFactory.createNameLabel(null);
//			model.setDsType(GlobalDefine.Type_CompositeEA);
		}
		return model;
	}

	private AbstractModel convertComposite(Sys sys) {
		AbstractModel model = null;
		Composite composite = (Composite) sys.content.picked;
		if (sys.type.name().equals(Type.Data.name())) {
			model = DSDiagramFactory.createCompositeData();
		} else if (sys.type.name().equals(Type.Predicate.name())) {
			model = DSDiagramFactory.createCompositePredicate();
		} else if (sys.type.name().equals(Type.Protocol.name())) {
			model = DSDiagramFactory.createCompositeProtocol();
		} else if (sys.type.name().equals(Type.System.name())) {
			model = DSDiagramFactory.createCompositeSystem();
		} else if (sys.type.name().equals(Type.Work.name())) {
			model = DSDiagramFactory.createCompositeWork();
		} else if (sys.type.name().equals(Type.NameLabel.name())){
			model = DSDiagramFactory.createNameLabel(null);
			if(sys.specSys.picked instanceof SNameLabel){
//				model.setDsType(getNameLabelDSType(((SpecNameLabel) sys.specSys.picked).name()));
			}
		//	
		}

		if(composite.subSys != null){
			for (Sys subSys : composite.subSys.inst) {
				AbstractModel child = convertSys(subSys);
				if(child != null){
					model.addChild(child);
				}			
			}
		}
		
		return model;
	}
		
	public int getNameLabelDSType(String sysType){
		int type = 0;
//		if(sysType.equals(SpecNameLabel.Data.name())){
//			type = GlobalDefine.Type_CompositeData;
//		} else if(sysType.equals(SpecNameLabel.Predicate.name())){
//			type = GlobalDefine.Type_CompositePredicate;
//		} else if(sysType.equals(SpecNameLabel.Protocol.name())){
//			type = GlobalDefine.Type_CompositeEA;
//		} else if(sysType.equals(SpecNameLabel.System.name())){
//			type = GlobalDefine.Type_COMPOSITE_SYSTEM;
//		} else if(sysType.equals(SpecNameLabel.Work.name())){
//			type = GlobalDefine.Type_COMPOSITE_WORK;
//		}
		return type;
	}

	public AbstractModel convertBeginPoint() {
		return null;
	}

	public AbstractModel convertExitPoint() {
		return null;
	}

	public AbstractModel convertEndPoint() {
		return null;
	}

	public Rectangle convertConstraint(Sys sys) {
		dsc.model.view.SysForView.Complete.Sys.ShowInfo.Rectangle rect = sys.showInfo.rectangle;
		if(sys.superSys.target instanceof Sys
				&& ((Sys)sys.superSys.target).showInfo != null
				&& ((Sys)sys.superSys.target).showInfo.showLabel != null
				&& ((Sys)sys.superSys.target).showInfo.showLabel.name().equals(YesNo.yes.name())){
			rect.y += 24;//GlobalDefine.LABEL_H;
		}
		Rectangle constraint = new Rectangle(rect.x, rect.y, rect.w, rect.h);
		return constraint;
	}

	public AbstractConnectionModel convertLink(Link link) {
		AbstractConnectionModel conn = null;
		Node source,target = null;
		if(link.linkType == null){
			return null;
		}
		if(link.linkType.name().equals(LinkType.create.name())){
			conn = new DynamicCreation();
			((DynamicCreation)conn).setName(link.content.toString());
		}else if(link.linkType.name().equals(LinkType.inherit.name())){
			conn = new Specialization();
			//还有属性需要设置
		}else if(link.linkType.name().equals(LinkType.interaction.name())){
			conn = new Interaction();
			((Interaction)conn).setName(link.content.toString());
		}else if(link.linkType.name().equals(LinkType.relation.name())){
			conn = new RelationLink();
			//还有属性需要设置
		}else if(link.linkType.name().equals(LinkType.transition.name())){
			conn = new Transition();
			((Transition)conn).setCondition(link.content.toString());
		}
		for(AbstractModel model : models){
			String name = model.getName();
			String tarName = "";
			String srcName = "";
			if(link.to.target instanceof AbstractSysForViewModel){
				tarName = JsonConvert.instance().linkNode2Json((AbstractSysForViewModel)link.to.target).toString();
			}else if(link.to.target instanceof String){
				tarName = (String) link.to.target;
			}
			if(link.from.target instanceof AbstractSysForViewModel){
				srcName = JsonConvert.instance().linkNode2Json((AbstractSysForViewModel)link.from.target).toString();
			}else if(link.from.target instanceof String){
				srcName = (String) link.from.target;
			}
			
			AbstractModel parent = model.getParent();
			while(!(parent instanceof ContentsModel)){
				name = parent.getName() + "." + name;
				parent = parent.getParent();
			}
			if(name.equals(srcName/*((AbstractSysForViewModel)link.from.target).name.toString()*/)){
				conn.setSource((Node) model);
				conn.attachSource();
			}
			if(link.to.target instanceof AbstractSysForViewModel
					&& name.equals(tarName/*((AbstractSysForViewModel)link.to.target).name.toString()*/)){
				conn.setTarget((Node) model);
				conn.attachTarget();
			}
		}
		conn.setSourceAnchorAngle(link.showInfo.fromAngle);
		conn.setTargetAnchorAngle(link.showInfo.toAngle);
		return conn;
	}

	public void writeFile(SysForView sysForView, String fileName)
			throws IOException {
		// IFile file = ((IFileEditorInput) getEditorInput())
		// .getFile();
		ContentsModel contentModel = this.convertSysForView(sysForView);
		// FileOutputStream out = new FileOutputStream(fileName);
		// XStreamHelper.writeObject(out, contentModel);
		// out.close();
		File file = new File(fileName);
		if (false == file.exists()) {
			try {
				file.createNewFile();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
		if (false == file.isFile()) {
			return;
		}

		try {
			// The value "false" for FileOutputStream means that overwrite this
			// file,
			// if it is "true",append the new data to this file.
			ObjectOutputStream oos = new ObjectOutputStream(
					new FileOutputStream(file, false));
			oos.writeObject(contentModel);
			oos.flush();
			oos.close();
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	public static void main(String[] args) {
		GefModelUtil mUtil = GefModelUtil.instance();
		Object obj = mUtil
				.readFile("C:\\Documents and Settings\\Administrator\\桌面\\webEditor\\eclipse\\showInfo.dsc");
		Sys sys = new Sys();
		Array<Link> links = new Array<Link>();
		mUtil.convertContentsModel((ContentsModel) obj, sys, links);
		Complete complete = new Complete();
		complete.link = links;
	//	complete.sys = sys.content.composite().subSys;
		SysForView sysForView = new SysForView();
		sysForView.pick = SysForView.complete_id;
		sysForView.picked = complete;

		GefConvert convert = GefConvert.getInstance();
		String fileName = "C:\\Documents and Settings\\Administrator\\桌面\\webEditor\\eclipse\\ss.dsc";
		try {
			convert.writeFile(sysForView, fileName);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
